package com.yjd.pub.user.service;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.app.model.PushRegidModel;
import com.yjd.comm.app.service.IPushRegidService;
import com.yjd.comm.base.dao.IBaseDao;
import com.yjd.comm.base.enums.DbWREnums;
import com.yjd.comm.base.service.impl.BaseServiceImpl;
import com.yjd.comm.device.model.DeviceModel;
import com.yjd.comm.device.service.IDeviceService;
import com.yjd.comm.enums.DeviceStatus;
import com.yjd.comm.funds.model.FundsModel;
import com.yjd.comm.funds.service.IFundsService;
import com.yjd.comm.msg.MnsMsgInfo;
import com.yjd.comm.system.model.SysParamModel;
import com.yjd.comm.system.util.SysParamUtil;
import com.yjd.comm.user.dto.UserSession;
import com.yjd.comm.user.model.UserDataModel;
import com.yjd.comm.user.model.UserModel;
import com.yjd.comm.user.service.IUserService;
import com.yjd.comm.util.FrameUtil;
import com.yjd.comm.util.SecurityCode;
import com.yjd.comm.util.StringUtil;
import com.yjd.comm.vo.Constant;
import com.yjd.msg.comm.annotation.MnsDispose;
import com.yjd.msg.comm.annotation.MnsMsg;
import com.yjd.msg.comm.enums.MsgOrderServiceEnum;
import com.yjd.msg.comm.enums.MsgTypeEnum;
import com.yjd.msg.comm.util.MnsUtils;
import com.yjd.pub.user.dao.IUserDao;
import com.yjd.pub.user.dao.IUserDataDao;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <b>description</b>：用户业务实现<br>
 * <b>time</b>：2017-06-27 08:58:59 <br>
 * <b>author</b>：  yangchangyan@yijiedai.com
 */
@Service("userService")
public class UserServiceImpl extends BaseServiceImpl implements IUserService {

	/**
	 * 插入
	 * 
	 * @param model
	 * @return
	 * @throws Exception
	 */
	public UserModel insert(UserModel model) throws Exception {
		return this.userDao.insertModel(model, true);
	}

	/**
	 * 更新
	 * 
	 * @param model
	 * @return
	 * @throws Exception
	 */
	public int update(UserModel model) throws Exception {
		return this.userDao.updateModel(model, true);
	}

	/**
	 * 根据id删除
	 * 
	 * @param user_id
	 * @return
	 * @throws Exception
	 */
	public int delete(long user_id) throws Exception {
		Map<Object, Object> paramMap = new HashMap<Object, Object>();
		paramMap.put("user_id", user_id);
		return this.userDao.deleteModel(paramMap, true);
	}

	/**
	 * 获取用户信息
	 *
	 * @param idUser
	 * @return UserSession
	 * @throws Exception
	 */
	@Override
	public UserSession getUserSession(Long idUser) throws Exception {
		if(idUser==null){
			FrameUtil.throwBaseException1("请求参数异常");
		}
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("idUser", idUser);
		return userDao.getUserSession(paramMap);
	}
	/**
	 * 手机号是否被占用
	 *
	 * @param mobile
	 * @return boolean
	 */
	@Override
	public boolean mobileIsExits(String mobile) throws Exception {
		if(StringUtil.isEmpty(mobile)){
			FrameUtil.throwBaseException1("请求参数异常");
		}
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("mobile_number", mobile);
		UserModel uModel = userDao.getModelOne(paramMap,true);
		if (uModel != null) {
			return true;
		}
		return false;
	}

	/**
	 * 手机端注册
	 *
	 * @param pwd        密码
	 * @param mphoneNo   手机号
	 * @param deviceNo   终端号
	 * @param deviceName 终端名称
	 * @param ip         ip地址
	 * @return mobile_type
	 * @throws Exception
	 */
	@Override
	public UserModel regModel(String pwd, String mphoneNo, String deviceNo, String deviceName, String regid, String ip) throws Exception {

		Long time = FrameUtil.getTime(null);
		// 校验手机
		if (!validMobileNumber(mphoneNo) || !validPassword(pwd)) {
			return null;
		}
		//初始化用户表
		UserModel userModel = new UserModel();
		userModel.setEncrypt(SecurityCode.getRandomCode(6));
		userModel.setPassword(SecurityCode.passwordMD5(pwd,
				userModel.getEncrypt()));
		userModel.setMobile_number(Long.parseLong(mphoneNo));
		userModel.setRegistration_ip(ip);
		userModel.setRegistration_time(time);
		userModel.setCreate_time(time);
		userModel.setLast_update_time(time);
		userModel = this.insert(userModel);

		//初始化用户信息表
		UserDataModel userDataModel = new UserDataModel();
		userDataModel.setUser_id(userModel.getUser_id());
		userDataModel.setCreate_time(time);
		userDataModel.setLast_update_time(time);
		userDataDao.insertModel(userDataModel,true);

		//初始化资金账户表
		FundsModel fundsModel = new FundsModel();
		fundsModel.setUser_id(userModel.getUser_id());
		fundsModel.setUpdate_time(time);
		fundsService.insert(fundsModel);

		// 更新用户设备信息
		insertOrUpdateDeviceModel(deviceNo, userModel.getUser_id(), deviceName);

		DeviceModel deviceModel = deviceService.getDeviceModelByDeviceNo(deviceNo);
		if (deviceModel == null) {
			FrameUtil.throwBaseException1("没有找到设备：" + deviceNo);
		}

		//记录极光推送id
		if (StringUtil.isNotEmpty(regid)) {
			PushRegidModel regidModel = pushRegidService.getModelOne(FrameUtil.newHashMap("user_id", userModel.getUser_id()), DbWREnums.READ);
			if(null == regidModel){
				regidModel = new PushRegidModel();
				regidModel.setUser_id(userModel.getUser_id());
				regidModel.setRegid(regid);
				regidModel.setCreate_time(time);
				pushRegidService.insert(regidModel);
			}else{
				regidModel.setRegid(regid);
				regidModel.setCreate_time(time);
				pushRegidService.updateByMap(regidModel);
			}
		}

		return userModel;
	}

	/**
	 * 验证手机号
	 *
	 * @param mphoneNo
	 *            手机号码
	 * @return boolean
	 * @throws Exception
	 */
	protected boolean validMobileNumber(String mphoneNo) throws Exception {
		if (mphoneNo == null) {
			FrameUtil.throwBaseException1("为了您的账户安全,请绑定手机哟!");
		}
		// 全部是数字
		if (!NumberUtils.isNumber(mphoneNo)) {
			FrameUtil.throwBaseException1("为了您的账户安全,请输入正确的手机号哟!");
		}

		// 正则验证
		SysParamModel sysParamModel = SysParamUtil.getSysParamModel(Constant.SysParamKeyEnum.REGISTER_REGEX);
		if (sysParamModel != null) {
			Matcher name = Pattern.compile(sysParamModel.getParam_value())
					.matcher(mphoneNo);
			if (!name.matches()) {
				FrameUtil.throwBaseException1("为了您的账户安全,请输入正确的手机号哟!");
			}
		}

		// 是否已经被使用了
		if (this.mobileIsExits(mphoneNo)) {
			FrameUtil.throwBaseException1("该手机号码已注册!");
		}

		return true;
	}

	/**
	 * 密码验证
	 *
	 * @param password
	 * @return boolean
	 * @throws Exception
	 */
	protected boolean validPassword(String password) throws Exception {
		if (StringUtils.isBlank(password)) {
			FrameUtil.throwBaseException1("密码可不能忘了设置哟!");
		}
		// 密码不能是中文
		Matcher m = Pattern.compile("[\u4e00-\u9fa5]").matcher(password);
		if (m.matches()) {
			FrameUtil.throwBaseException1("密码不能包含中文哟!");
		}
		if (password.length() < 6) {
			FrameUtil.throwBaseException1("密码不能至少6位");
		}
		return true;
	}

	/**
	 * 更新设备表
	 *
	 * @param deviceNo
	 *            设备编号
	 * @param idUser
	 *            用户主键 void
	 * @throws Exception
	 */
	private void insertOrUpdateDeviceModel(String deviceNo, Long idUser, String deviceName) throws Exception {
		Long time = FrameUtil.getTime(null);

		// 用户是否有其他设备正在使用中，如果有则更新其他设备为未使用
		DeviceModel device = deviceService.getDeviceModelByUser(idUser);
		if (device != null) {
			String curDeviceNo = device.getDevice_no(); // 当前使用的设备
			// 当前使用的设备号和正在登陆的设备号
			if (!deviceNo.equals(curDeviceNo)) {
				// 1. 更新登录用户的其他设备为未使用状态
				// 2. 更新当前登录设备上的其他用户为下线状态
				this.updateStatus(idUser, deviceNo, time);
			}
		}

		// 根据设备号查询设备详细信息
		DeviceModel deviceModel = deviceService.getDeviceModelByDeviceNo(deviceNo);
		// 如果该设备已经存在,则更新设备状态为使用中
		if (deviceModel != null) {
			Long device_id = deviceModel.getDevice_id();
			// 更新用户当前使用的设备
			if (!this.updateDeviceUser(idUser, time, device_id)) {
				throw new Exception("更新用户当前使用设备信息失败");
			}
		}

		// 如果没有该设备则添加设备，设备默认状态为使用中
		if (deviceModel == null) {
			deviceModel = this.insertDeviceModel(deviceNo, idUser, deviceName, time);
			if (deviceModel == null) {
				throw new Exception("插入设备信息失败");
			}
		}
	}

	/**
	 * 更新设备使用状态
	 *
	 * @param idUser
	 * @param time
	 * @return boolean
	 * @throws Exception
	 */
	private void updateStatus(Long idUser, String curDeviceNo, Long time) throws Exception {
		DeviceModel deviceModel = new DeviceModel();
		deviceModel.setUser_id(idUser);
		deviceModel.setLast_update_time(time);
		deviceModel.setInuse(DeviceStatus.unable.getCode());
		if (!deviceService.updateDeviceStatus(deviceModel)) {
			FrameUtil.throwBaseException1("更新该用户其他设备信息失败：" + idUser);
		}
		deviceModel.setDevice_no(curDeviceNo);
		deviceModel.setUser_id(null);

		if (!deviceService.updateDeviceStatus(deviceModel)) {
			FrameUtil.throwBaseException1("更新设备:" + curDeviceNo + "上的其他用户的状态失败");
		}
	}


	/**
	 * 更新设备用户信息
	 *
	 * @param idUser
	 * @param time
	 * @param device_id
	 * @return
	 * @throws Exception
	 *             boolean
	 */
	private boolean updateDeviceUser(Long idUser, Long time, Long device_id)
			throws Exception {
		DeviceModel deviceModel = new DeviceModel();
		// 更新用户当前使用的设备
		deviceModel.setDevice_id(device_id);
		deviceModel.setUser_id(idUser);
		deviceModel.setLast_update_time(time);
		deviceModel.setInuse(DeviceStatus.enable.getCode());
		deviceModel.setLast_login_time(time);
		return deviceService.update(deviceModel) == 1;
	}

	/**
	 * 添加设备信息
	 *
	 * @param deviceNo
	 *            设备编号
	 * @param idUser
	 *            用户号
	 * @param deviceName
	 *            设备名称
	 * @param time
	 *            操作日期
	 * @return DeviceModel
	 * @throws Exception
	 */
	private DeviceModel insertDeviceModel(String deviceNo, Long idUser,
										  String deviceName, Long time) throws Exception {
		DeviceModel deviceModel = new DeviceModel();
		deviceModel.setDevice_no(deviceNo);
		deviceModel.setUser_id(idUser);
		deviceModel.setDevice_name(deviceName);
		deviceModel.setInuse(DeviceStatus.enable.getCode());
		deviceModel.setCreate_time(time);
		deviceModel.setLast_update_time(time);
		deviceModel.setLast_login_time(time);
		return deviceService.insert(deviceModel);
	}

	/**
	 * 用户登陆
	 *
	 * @param mobile_number
	 * @param password
	 * @return
	 * @throws Exception
	 */
	public UserModel login(String mobile_number, String password) throws Exception {

		// user noet exist
		UserModel dbUser = userDao.getModelOne(FrameUtil.newHashMap("mobile_number", mobile_number), DbWREnums.READ.isWrite());
		if(null == dbUser){
			return null;
		}

		// 用户输入的密码
		String currentPwd = SecurityCode.passwordMD5(password.trim(), dbUser.getEncrypt());

		// 数据库中用户的密码
		String dbpwd = dbUser.getPassword();

		if (dbpwd.equals(currentPwd)) {
			return dbUser;
		}

		return null;
	}


	/**
	 * 修改交易密码
	 *
	 * @param idUser   用户号
	 * @param password 密码
	 * @return session
	 * @throws Exception
	 */
	@Override
	public boolean modifyPayPassword(Long idUser, String password) throws Exception {
		if (idUser == null || org.apache.commons.lang3.StringUtils.isBlank(password)) {
			FrameUtil.throwBaseException1("参数不完整");
		}
		UserModel saltModel = this.getModelById(idUser, DbWREnums.READ);
		if (saltModel == null) {
			FrameUtil.throwBaseException1("用户不存在:" + idUser);
		}
		UserModel uModel = new UserModel();
		uModel.setUser_id(idUser);
		String pwdMd5 = SecurityCode.passwordMD5(password, saltModel.getEncrypt());
		uModel.setPay_password(pwdMd5);

		if(this.update(uModel) != 1){
			FrameUtil.throwBaseException1("操作失败");
		}
		return true;
	}
	@Override
	@MnsMsg
	public void MsgDemo(Long id) throws Exception {
		UserModel userModel = new UserModel();
		userModel.setUser_id(id);
		userModel.setMobile_number(13689566+id);
		userModel.setUser_type(1);
		MnsUtils.createMessage(id+"", MsgTypeEnum.ORDER_MSG_DEMO, MsgOrderServiceEnum.PUBLIC_ORDER_SERVICE,userModel);
	}

	@Override
	@MnsDispose
	public void MsgDisposeDemo(MnsMsgInfo mnsMsgInfo) throws Exception {
		logger.info("业务处理类处理资金消息："+ JSON.toJSONString(mnsMsgInfo));
	}

	@Resource
	private IUserDao userDao;

	@Override
	public IBaseDao getBaseDao() {
		return this.userDao;
	}

	@Resource
	private IDeviceService deviceService;

	@Resource
	private IUserDataDao userDataDao;

	@Resource
	private IFundsService fundsService;

	@Resource
	private IPushRegidService pushRegidService;

}
